package geektime.concurrent.part2.race;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 单线程选手操作的类
 */
public class SingleThreadPlayer {

    private SingleThreadShareData shareData;

    public long genRandomNumbersAndCompute() throws InterruptedException {
        shareData = new SingleThreadShareData();
        System.out.println("------单线程选手开始工作了------");
        // 创建一个线程用于生产随机数
        long t0 = System.currentTimeMillis();
        GenRandomNumberThread genRandomNumberThread = new GenRandomNumberThread();
        genRandomNumberThread.start();
        genRandomNumberThread.join();
        System.out.println("单线程选手生成随机数的数量=" + shareData.getScoreList().size());
        long t1 = System.currentTimeMillis();
        // 创建一个线程用于排序计算
        SortComputeThread sortComputeThread = new SortComputeThread();
        sortComputeThread.start();
        sortComputeThread.join();
        // main线程打印结果
        printTop10();
        long t2 = System.currentTimeMillis();
        System.out.printf("单线程选手生成随机数耗时=%s，排序计算耗时=%s，总耗时=%s\n", (t1 - t0), (t2 - t1), (t2 - t0));
        return (t2 - t0);
    }

    class GenRandomNumberThread extends Thread {
        @Override
        public void run() {
            Random random = new Random(System.currentTimeMillis());
            for (int i = 0; i < shareData.COUNT; i++) {
                shareData.getScoreList().add(new Integer(random.nextInt(shareData.COUNT)));
            }
            // 生成随机数据的动作完成后，将生成随机数状态置为true
            shareData.setConcurrentSignal(true);
        }
    }

    class SortComputeThread extends Thread {
        @Override
        public void run() {
            // 当生成随机数的动作还没有完成的时候，排序计算的线程通过休眠来自旋等待
            if (!shareData.getConcurrentSignal()) {
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 将scoreList转为数组后进行排序操作
            Integer[] scoreArray = shareData.getScoreList().toArray(new Integer[shareData.COUNT]);
            Arrays.sort(scoreArray);
            // 将大小靠前的BUF_SIZE个数字按照降序放到topArray中
            for (int i = 0; i < shareData.BUF_SIZE; i++) {
                shareData.getTopArray()[i] = scoreArray[shareData.COUNT - 1 -i];
            }
        }
    }

    private void printTop10() {
        System.out.print("单线程选手生成的最大的数字TOP10：");
        for (int i = 0; i < 10; i++) {
            System.out.print(shareData.getTopArray()[i] + " ");
        }
        System.out.println();
    }
}
